import cv2
import numpy as np
import pyautogui


def hex_to_hsv(hex_color):
    """
    将十六进制颜色代码转换为HSV颜色范围
    :param hex_color: 十六进制颜色代码，如 "ffff00"
    :return: 颜色的下限和上限（HSV格式）
    """
    # 将十六进制颜色代码转换为BGR格式
    bgr_color = np.array([int(hex_color[4:6], 16), int(hex_color[2:4], 16), int(hex_color[0:2], 16)], dtype=np.uint8)
    # 将BGR颜色转换为HSV颜色
    hsv_color = cv2.cvtColor(np.uint8([[bgr_color]]), cv2.COLOR_BGR2HSV)[0][0]

    # 定义颜色范围，微调容差
    hue = hsv_color[0]
    saturation = int(hsv_color[1])
    value = int(hsv_color[2])

    # 避免溢出
    upper_hue = min(180, hue + 10)
    upper_saturation = min(255, saturation + 50)
    upper_value = min(255, value + 50)

    lower_color = np.array([max(0, hue - 10), max(0, saturation - 50), max(0, value - 50)])
    upper_color = np.array([upper_hue, upper_saturation, upper_value])

    return lower_color, upper_color


def preprocess_image(image, lower_color, upper_color):
    """
    预处理图像：提取指定颜色区域并转为灰度图
    :param image: 输入的图像
    :param lower_color: 颜色的下限（HSV格式）
    :param upper_color: 颜色的上限（HSV格式）
    :return: 处理后的灰度图像
    """
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    # 高斯模糊
    blurred = cv2.GaussianBlur(hsv, (5, 5), 0)
    mask = cv2.inRange(blurred, lower_color, upper_color)
    color_only = cv2.bitwise_and(image, image, mask=mask)
    return cv2.cvtColor(color_only, cv2.COLOR_BGR2GRAY)


def detect_and_draw_circle(template_path, hex_color, threshold=0.7):
    lower_color, upper_color = hex_to_hsv(hex_color)
    # 获取全屏截图（BGR格式）
    screenshot = pyautogui.screenshot()
    screenshot_bgr = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
    gray_screenshot = preprocess_image(screenshot_bgr, lower_color, upper_color)

    # 加载模板
    template = cv2.imread(template_path)
    if template is None:
        print(f"错误：无法加载模板文件 {template_path}")
        return None

    template_gray = preprocess_image(template, lower_color, upper_color)
    h, w = template_gray.shape[:2]

    # 多尺度模板匹配
    best_score = float('inf')  # 对于TM_SQDIFF_NORMED，分数越低越好
    best_pos = (0, 0)
    best_scale = 1
    scales = np.linspace(0.5, 1.5, 15)  # 检测不同大小的目标

    for scale in scales:
        scaled_template = cv2.resize(template_gray, (0, 0), fx=scale, fy=scale)
        if scaled_template.shape[0] > gray_screenshot.shape[0] or scaled_template.shape[1] > gray_screenshot.shape[1]:
            continue

        result = cv2.matchTemplate(gray_screenshot, scaled_template, cv2.TM_SQDIFF_NORMED)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

        if min_val < best_score:
            best_score = min_val
            best_pos = min_loc
            best_scale = scale

    # 阈值判断
    if best_score <= 1 - threshold:  # 对于TM_SQDIFF_NORMED，需要调整阈值逻辑
        x, y = best_pos
        scaled_w = int(w * best_scale)
        scaled_h = int(h * best_scale)
        center = (x + scaled_w // 2, y + scaled_h // 2)  # 计算圆心
        radius = max(scaled_w, scaled_h) // 2  # 半径

        # 绘制红色圆圈（线宽4px，抗锯齿）
        cv2.circle(screenshot_bgr, center, radius, (0, 0, 255), 4, cv2.LINE_AA)

        # 显示结果
        cv2.imshow("全屏检测结果", screenshot_bgr)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
        print(f"检测成功！匹配度：{1 - best_score:.3f}，圆心坐标：{center}，半径：{radius}")
        return center, radius
    else:
        print(f"未检测到目标（最高匹配度：{1 - best_score:.3f} < {threshold}）")
        return None


def logic_1(template_path, hex_color, action_q, action_t, threshold=0.9):
    result = detect_and_draw_circle(template_path, hex_color, threshold)
    if result:
        while True:
            action_q()
            # 再次检测目标图像
            new_result = detect_and_draw_circle(template_path, hex_color, threshold)
            if not new_result:
                break
    else:
        action_t()


def logic_2(template_path, hex_color, action_m, action_n, threshold=0.9):
    result = detect_and_draw_circle(template_path, hex_color, threshold)
    if not result:
        while True:
            action_m()
            # 再次检测目标图像
            new_result = detect_and_draw_circle(template_path, hex_color, threshold)
            if new_result:
                action_n()
                break
    else:
        action_n()
